import numpy
import os
from numpy import arange, concatenate, zeros

class Mesh():
    def __init__(self, name):
        self.name = name
        self.vertices = zeros((3, 0), float)
        self.texCoords = zeros((2, 0), float)
        self.faces = []
        
    def addVertex(self, vertex):
        # add a vertex if it doesn't already exist and return its index
        nOld = self.vertices.shape[1]
        for i in range(nOld):
            if numpy.all(self.vertices[:, i] == vertex):
                return i
        else:
            vertex.shape = (3, 1)
            self.vertices = concatenate((self.vertices, vertex), 1)
            return nOld
            
    def addTexCoord(self, texCoord):
        nOld = self.texCoords.shape[1]
        for i in range(nOld):
            if numpy.all(self.texCoords[:, i] == texCoord):
                return i
        else:
            texCoord.shape = (2, 1)
            self.texCoords = concatenate((self.texCoords, texCoord), 1)
            return nOld

    def addFace(self, vertices, texCoords):
        #fixme: remove redundant vertices
        n = vertices.shape[1]
        face = [(self.addVertex(vertices[:, i]), self.addTexCoord(texCoords[:, i])) for i in range(n)]
        self.faces.append(face)

    def scale(self, s):
        s = numpy.diag(s)
        self.vertices = s * self.vertices

    def rotateAndScale(self, rs):
        self.vertices = rs * self.vertices
        
    def stringObj(self):
        result = ""
        result += "g " + self.name + "\n"
        result += "usemtl " + self.name + "\n"
        for iv in range(self.vertices.shape[1]):
            result += "v %f %f %f\n" % (self.vertices[0, iv], self.vertices[1, iv], self.vertices[2, iv])
        for ivt in range(self.texCoords.shape[1]):
            result += "vt %f %f\n" % (self.texCoords[0, ivt], self.texCoords[1, ivt])
        for face in self.faces:
            result += "f"
            for vertexIndex, texCoordIndex in face:
                result += " %d/%d" % (vertexIndex + 1, texCoordIndex + 1)
            result += "\n"
        return result

    def stringMtl(self, ka = (0.125, 0.125, 0.125), kd = (0.75, 0.75, 0.75), ks = (0.125, 0.125, 0.125)):
        result = ""
        result += "newmtl " + self.name + "\n"
        result += "Ka %f %f %f\n" % ka
        result += "Kd %f %f %f\n" % kd
        result += "Ks %f %f %f\n" % ks
        result += "map_Ka " + self.name + "_d.png\n"
        result += "map_Kd " + self.name + "_d.png\n"
        result += "Ns 16\n"
        return result

    def exportWavefront(self, targetDir = ""):
        objFile = open(os.path.join(targetDir, self.name + ".obj"), "w")
        objFile.write(self.stringObj())
        objFile.close()
        
        mtlFile = open(os.path.join(targetDir, self.name + ".mtl"), "w")
        mtlFile.write(self.stringMtl())
        mtlFile.close()

def indexToMeshCoord(ix, iy, nx, ny):
    x = ix - 0.5 * nx
    y = iy - 0.5 * ny
    return x, y
